# -*- coding: utf-8 -*-
# 三、功能需求约束
# 1.数据预处理：
# 必须使用MinMaxScaler对波士顿房价数据集的特征和目标变量进行缩放，以确保模型训练的稳定性和效率。
# 缩放后的数据应保留在适当的变量中，以供后续使用。
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']='SimHei'
import torch
from sklearn.datasets import load_boston

data, target = load_boston(return_X_y=True)
target = target.reshape(-1, 1)
from sklearn.preprocessing import MinMaxScaler

data = MinMaxScaler().fit_transform(data)
target = MinMaxScaler().fit_transform(target)
# 2.时间序列数据生成：
# 必须使用滑动窗口方法将原始数据转换为时间序列数据。
# 窗口大小（c）应设置为7，意味着每个输入特征将包含7个连续的时间点。
# 生成的时间序列数据应分为输入特征（x）和目标变量（y），并转换为PyTorch张量。
c = 7
x = []
y = []
for i in range(len(data) - c):
    x.append(data[i:i + c])
    y.append(target[i + c, -1])
x = torch.tensor(x, dtype=torch.float)
y = torch.tensor(y, dtype=torch.float).reshape(-1, 1)
# 3.模型构建与训练：
# 必须使用PyTorch框架定义一个线性回归模型，其输入特征数量为7 * 13（7个时间点的13个特征），输出特征数量为1（房价）。
# 必须定义均方误差损失函数（MSELoss）和Adam优化器。
# 模型应通过多次迭代进行训练，以最小化预测误差。训练过程中的损失值应打印出来，以便监控训练进度。
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, shuffle=False, random_state=42)
print(x_train.shape, y_train.shape)
model = torch.nn.Linear(in_features=7 * 13, out_features=1)
loss_fn = torch.nn.MSELoss()
optim_adam = torch.optim.Adam(model.parameters())
model.train()
for i in range(20000):
    optim_adam.zero_grad()
    h = model(x_train.reshape(-1, 7 * 13))
    loss = loss_fn(h, y_train)
    loss.backward()
    optim_adam.step()
    if i % 100 == 0:
        print(i + 1, loss)
# 4.结果预测与可视化：
# 必须使用训练好的模型对测试集进行预测，并将预测结果转换为NumPy数组。
# 必须将预测结果与真实房价进行可视化对比，以评估模型的预测性能。可视化应使用matplotlib库完成，预测结果和真实房价应分别用绿色和红色表示。
model.eval()
with torch.no_grad():
    h=model(x_test.reshape(-1,7*13))
    plt.plot(h,c='g',label='预测值')
    plt.plot(y_test,c='r',label='真实值')
    plt.legend()
    plt.show()
# 5.代码结构与可读性：
# 代码应具有良好的结构，每个步骤都应清晰地分隔开。
# 变量名应具有描述性，以便理解其用途。
# 注释应适当添加，以解释代码的功能和关键步骤。
# 6.性能与效率：
# 代码应尽可能高效，避免不必要的计算和数据复制。
# 训练过程中的内存使用应得到优化，以避免内存溢出。
# 7.可维护性与扩展性：
# 代码应易于维护和扩展，以便将来添加新的功能或修改现有功能。
# 应考虑使用函数或类来封装重复的代码块，以提高代码的可重用性。
